/*
 * This file is part of ELCube.
 *
 * ELCube is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * ELCube is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with ELCube.  If not, see <https://www.gnu.org/licenses/>.
 */
package cn.nkpro.elcube.components.financial.cards

import cn.nkpro.elcube.annotation.NkNote
import cn.nkpro.elcube.co.easy.EasySingle
import cn.nkpro.elcube.co.spel.NkSpELManager
import cn.nkpro.elcube.docengine.NkAbstractCard
import cn.nkpro.elcube.docengine.NkDocEngine
import cn.nkpro.elcube.docengine.model.DocDefIV
import cn.nkpro.elcube.docengine.model.DocHV
import cn.nkpro.elcube.financial.model.FinVoucherIV
import org.dom4j.Document
import org.dom4j.DocumentHelper
import org.dom4j.Element
import org.dom4j.io.OutputFormat
import org.dom4j.io.XMLWriter
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.core.annotation.Order
import org.springframework.stereotype.Component

@Order(100015)
@NkNote("用友NC财务凭证模版-不要使用")
@Component("NkCardAccountingNCTemplate")
class NkCardAccountingNCTemplate extends NkAbstractCard<Data,Def> {

    @Autowired
    private NkSpELManager spELManager
    @Autowired
    private NkDocEngine docEngine


    @Override
    Data calculate(DocHV doc, Data data, DocDefIV defIV, Def d, boolean isTrigger, Object options) {

        if(d.engineCardKey){
            EasySingle single = doc.fetch(d.engineCardKey)
            if(single){

                DocHV prev = doc.preDocId?docEngine.detail(doc.preDocId):null

                def context = spELManager.createContext(doc)
                context.setVariable("\$prev",prev)

                Document document = DocumentHelper.createDocument()
                document.setXMLEncoding("UTF-8")

                Element root = document.addElement("ufinterface")
                Element voucher = root.addElement("voucher")
                Element voucher_head = voucher.addElement("voucher_head")

                if(d.attrs){
                    root.addAttribute("account",d.attrs.account)
                            .addAttribute("billtype",d.attrs.billtype)
                            .addAttribute("groupcode",d.attrs.groupcode)
                            .addAttribute("orgcode",d.attrs.orgcode)
                            .addAttribute("sender",d.attrs.sender)
                }

                if(d.heads){
                    voucher_head.addElement("pk_vouchertype").setText(d.heads.pk_vouchertype)
                    voucher_head.addElement("voucherkind").setText(d.heads.voucherkind)
                    voucher_head.addElement("pk_system").setText(d.heads.pk_system)
                    voucher_head.addElement("pk_group").setText(d.heads.pk_group)
                    voucher_head.addElement("pk_org").setText(d.heads.pk_org)
                    voucher_head.addElement("pk_org_v").setText(d.heads.pk_org_v)
                    voucher_head.addElement("pk_accountingbook").setText(d.heads.pk_accountingbook)
                    voucher_head.addElement("signflag").setText(d.heads.signflag)

                    data.pk_vouchertype     = d.heads.pk_vouchertype
                    data.voucherkind        = d.heads.voucherkind
                    data.pk_system          = d.heads.pk_system
                    data.pk_group           = d.heads.pk_group
                    data.pk_org             = d.heads.pk_org
                    data.pk_org_v           = d.heads.pk_org_v
                    data.pk_accountingbook  = d.heads.pk_accountingbook
                    data.signflag           = d.heads.signflag

                    data.year               = single.get("accountYear") as String
                    data.period             = single.get("accountPeriod") as String

                    voucher_head.addElement("year").setText(data.year)
                    voucher_head.addElement("period").setText(data.period)

                    if(d.heads.attachmentSpEL){
                        data.attachment = spELManager.invoke(d.heads.attachmentSpEL,context) as String
                        voucher_head.addElement("attachment").setText(data.attachment)
                    }
                    if(d.heads.noSpEL){
                        data.no = spELManager.invoke(d.heads.noSpEL,context) as String
                        voucher_head.addElement("no").setText(data.no)
                    }
                    if(d.heads.pk_preparedSpEL) {
                        data.pk_prepared = spELManager.invoke(d.heads.pk_preparedSpEL,context) as String
                        voucher_head.addElement("pk_prepared").setText(data.pk_prepared)
                    }
                }
                Element details = voucher_head.addElement("details")

                List<FinVoucherIV> items = single.get("items")
                if(items){
                    items.forEach{item->

                        Element elementItem          = details.addElement("item")
                        elementItem.addElement("detailindex")       //分录号 非空
                                .setText(item.itemIndex as String)
                        elementItem.addElement("explanation")       //摘要 非空
                                .setText(item.explanation)
                        elementItem.addElement("verifydate")        //业务日期 可空
                        elementItem.addElement("price")             //单价 可空
                        elementItem.addElement("excrate2")          //折本汇率 可空
                        elementItem.addElement("pk_currtype")       //币种 非空
                                .setText(item.currType)
                        elementItem.addElement("pk_accasoa")        //科目 非空
                                .setText(item.voucherSubject)
                        elementItem.addElement("pk_unit")           //所属二级核算单位 可空（组织）
                        elementItem.addElement("pk_unit_v")         //所属二级核算单位版本 可空（组织）


                        if(item.debitAmount!=null){
                            elementItem.addElement("debitquantity")     //借方数量 可空
                            elementItem.addElement("debitamount")       //原币借方金额 可空
                                    .setText(item.debitAmount as String)
                            elementItem.addElement("localdebitamount")  //本币借方金额 可空
                            elementItem.addElement("groupdebitamount")  //集团本币借方金额 可空
                            elementItem.addElement("globaldebitamount") //全局本币借方金额 可空
                        }else{
                            elementItem.addElement("creditquantity")    //贷方数量 可空
                            elementItem.addElement("creditamount")      //原币贷方金额 可空
                                    .setText(item.creditAmount as String)
                            elementItem.addElement("localcreditamount") //本币贷方金额 可空
                            elementItem.addElement("groupcreditamount") //集团本币贷方金额 可空
                            elementItem.addElement("globalcreditamount")//全局本币贷方金额 可空
                        }


                        if(item.assists){
                            Element elementAss = elementItem.addElement("ass")
                            item.assists.forEach({ ass ->
                                Element elementAssItem = elementAss.addElement("item")
                                elementAssItem.addElement("pk_Checktype").setText(ass.key)
                                elementAssItem.addElement("pk_Checkvalue").setText(ass.value)
                            })
                        }

                        if(item.cashFlow){
                            Element elementCashFlowItem = elementItem.addElement("cashFlow")
                                    .addElement("item")
                            def amount = (item.creditAmount ?: item.debitAmount ?: 0 ) * item.cashFlowSide

                            elementCashFlowItem.addElement("pk_cashflow").setText(item.cashFlow)
                            elementCashFlowItem.addElement("m_pk_currtype").setText(item.currType)
                            elementCashFlowItem.addElement("money").setText(amount as String)
                            elementCashFlowItem.addElement("moneyglobal").setText(amount as String)
                            elementCashFlowItem.addElement("moneygroup").setText(amount as String)
                            elementCashFlowItem.addElement("moneymain").setText(amount as String)
                        }

                    }
                }
                //创建输出格式
                OutputFormat format = OutputFormat.createPrettyPrint()
                format.setEncoding("UTF-8")
                StringWriter writer = new StringWriter()
                XMLWriter xmlWriter = new XMLWriter( writer, format )
                xmlWriter.write(document)
                data.xml = writer.toString()
                writer.close()
            }
        }

        return super.calculate(doc, data, defIV, d, isTrigger, options) as Data
    }

    @Override
    Data beforeUpdate(DocHV doc, Data data, Data original, DocDefIV defIV, Def d) {

        if(d.conditionSpEL){
            if(spELManager.invoke(d.conditionSpEL, doc) as Boolean){
                // 调用NC接口
            }
        }

        return super.beforeUpdate(doc, data, original, defIV, d) as Data
    }

    @SuppressWarnings("unused")
    static class Data implements Serializable{
        String xml

        String pk_vouchertype
        String voucherkind
        String pk_system
        String pk_group
        String pk_org
        String pk_org_v
        String pk_accountingbook
        String signflag

        String year
        String period
        String attachment
        String no
        String pk_prepared
    }

    static class Def implements Serializable{
        String conditionSpEL
        String engineCardKey
        AttrDef attrs
        HeadDef heads
    }
    static class AttrDef implements Serializable{
        String account
        String billtype
        String groupcode
        String orgcode
        String sender
    }
    static class HeadDef implements Serializable{
        String pk_vouchertype
        String voucherkind
        String pk_system
        String pk_group
        String pk_org
        String pk_org_v
        String pk_accountingbook
        String signflag

        String yearSpEL
        String periodSpEL
        String attachmentSpEL
        String noSpEL
        String pk_preparedSpEL

    }
}
